<%
Class FastAsp_Template
    Private m_TemplateDir  '模板目录
    Private m_TemplateExt  '模板后缀
    Private m_ParseVars    '解析变量
    Private m_Content      '模板内容
    Private m_Cache        '是否缓存
    Private m_CacheTime    '缓存时间
    Private m_Debug        '调试模式
    
    Private Sub Class_Initialize()
        m_TemplateDir = GetConfig("TemplateDir")
        If m_TemplateDir = "" Then m_TemplateDir = "/templates"
        m_TemplateExt = GetConfig("TemplateExt")
        If m_TemplateExt = "" Then m_TemplateExt = ".html"
        m_Cache = GetConfig("TemplateCache")
        m_CacheTime = GetConfig("CacheTime")
        m_Debug = GetConfig("DebugMode")
        Set m_ParseVars = Server.CreateObject("Scripting.Dictionary")
    End Sub
    
    '设置模板目录
    Public Function SetDir(byval dir)
        m_TemplateDir = dir
        Set SetDir = Me
    End Function
    
    '设置模板后缀
    Public Function SetExt(byval ext)
        m_TemplateExt = ext
        Set SetExt = Me
    End Function
    
    '设置变量
    Public Function Assign(byval key, byval value)
        m_ParseVars(key) = value
        Set Assign = Me
    End Function
    
    '批量设置变量
    Public Function AssignArray(byval arr)
        Dim key
        For Each key In arr.Keys
            m_ParseVars(key) = arr(key)
        Next
        Set AssignArray = Me
    End Function
    
    '显示模板
    Public Sub Display(byval file)
        m_Content = LoadTemplate(file)
        ParseTemplate()
        Response.Write m_Content
    End Sub
    
    '获取解析后的内容
    Public Function Fetch(byval file)
        m_Content = LoadTemplate(file)
        ParseTemplate()
        Fetch = m_Content
    End Function
    
    '解析模板
    Private Sub ParseTemplate()
        '解析变量
        ParseVars()
        
        '解析Include标签
        ParseIncludeTag()
        
        '解析For标签
        ParseForTag()
        
        '解析Volist标签
        ParseVolistTag()
        
        '解析If标签
        ParseIfTag()
        
        '解析Switch标签
        ParseSwitchTag()
        
        '解析分页标签
        ParsePagerTag()
        
        '解析内置函数
        ParseFunction()
        
        '解析Session
        ParseSession()
        
        '解析Cookie
        ParseCookie()
        
        '解析公共函数
        ParseCommon()
    End Sub
    
    '解析变量
    Private Sub ParseVars()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{\$([^\}]+)\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, varName, varValue
        For Each match In matches
            varName = match.SubMatches(0)
            
            '支持对象属性访问
            If InStr(varName, ".") > 0 Then
                varValue = GetObjectValue(varName)
            ElseIf m_ParseVars.Exists(varName) Then
                varValue = m_ParseVars(varName)
            Else
                varValue = ""
            End If
            
            m_Content = Replace(m_Content, match.Value, varValue)
        Next
    End Sub
    
    '解析For标签
    Private Sub ParseForTag()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{for\s+start=""(\d+)""\s+end=""(\d+)""\}([\s\S]*?)\{/for\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, start, end_, content, result, i
        For Each match In matches
            start = CInt(match.SubMatches(0))
            end_ = CInt(match.SubMatches(1))
            content = match.SubMatches(2)
            result = ""
            
            For i = start To end_
                result = result & Replace(content, "{$i}", i)
            Next
            
            m_Content = Replace(m_Content, match.Value, result)
        Next
    End Sub
    
    '解析Volist标签
    Private Sub ParseVolistTag()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{volist\s+name=""([^""]+)""\s+id=""([^""]+)""\}([\s\S]*?)\{/volist\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, name, id, content, data, result, i, item
        For Each match In matches
            name = match.SubMatches(0)
            id = match.SubMatches(1)
            content = match.SubMatches(2)
            result = ""
            
            '获取数据源
            If m_ParseVars.Exists(name) Then
                data = m_ParseVars(name)
                
                '处理数组
                If IsArray(data) Then
                    For i = 0 To UBound(data)
                        result = result & ParseVolistItem(content, id, data(i))
                    Next
                '处理字典对象
                ElseIf TypeName(data) = "Dictionary" Then
                    For Each item In data.Items
                        result = result & ParseVolistItem(content, id, item)
                    Next
                End If
            End If
            
            m_Content = Replace(m_Content, match.Value, result)
        Next
    End Sub
    
    '解析Volist项目
    Private Function ParseVolistItem(byval content, byval id, byval item)
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{\$" & id & "(?:\.([^\}]+))?\}"
        
        Dim result : result = content
        Dim matches : Set matches = reg.Execute(content)
        Dim match, key, value
        
        For Each match In matches
            If match.SubMatches(0) = "" Then
                value = item
            Else
                key = match.SubMatches(0)
                If TypeName(item) = "Dictionary" Then
                    value = item(key)
                Else
                    value = Eval("item." & key)
                End If
            End If
            result = Replace(result, match.Value, value)
        Next
        
        ParseVolistItem = result
    End Function
    
    '解析分页标签
    Private Sub ParsePagerTag()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{pager\s+total=""([^""]+)""(?:\s+style=""([^""]+)"")?\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, total, style, page
        For Each match In matches
            total = GetVarValue(match.SubMatches(0))
            style = match.SubMatches(1)
            
            Set page = New FastAsp_Page
            page.TotalRows = total
            If style <> "" Then page.Style = style
            
            m_Content = Replace(m_Content, match.Value, page.Show())
        Next
    End Sub
    
    '解析内置函数
    Private Sub ParseFunction()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{:([^\}]+)\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, func, result
        For Each match In matches
            func = match.SubMatches(0)
            result = Eval(func)
            m_Content = Replace(m_Content, match.Value, result)
        Next
    End Sub
    
    '解析Session
    Private Sub ParseSession()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{session\.([^\}]+)\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, key
        For Each match In matches
            key = match.SubMatches(0)
            m_Content = Replace(m_Content, match.Value, Session(key))
        Next
    End Sub
    
    '解析Cookie
    Private Sub ParseCookie()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{cookie\.([^\}]+)\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, key
        For Each match In matches
            key = match.SubMatches(0)
            m_Content = Replace(m_Content, match.Value, Request.Cookies(key))
        Next
    End Sub
    
    '解析公共函数
    Private Sub ParseCommon()
        '可以在这里添加更多公共函数的解析
        ParseDateFormat()
        ParseStringFormat()
        ParseNumberFormat()
    End Sub
    
    '解析日期格式化
    Private Sub ParseDateFormat()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{date\s+format=""([^""]+)""\s+value=""([^""]+)""\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, format, value
        For Each match In matches
            format = match.SubMatches(0)
            value = GetVarValue(match.SubMatches(1))
            m_Content = Replace(m_Content, match.Value, FormatDateTime(value, format))
        Next
    End Sub
    
    '解析字符串格式化
    Private Sub ParseStringFormat()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{string\s+length=""(\d+)""\s+value=""([^""]+)""\s*(?:pad=""([^""]+)"")?\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, length, value, pad
        For Each match In matches
            length = match.SubMatches(0)
            value = GetVarValue(match.SubMatches(1))
            pad = match.SubMatches(2)
            If pad = "" Then pad = " "
            
            m_Content = Replace(m_Content, match.Value, RightPad(value, length, pad))
        Next
    End Sub
    
    '解析数字格式化
    Private Sub ParseNumberFormat()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{number\s+format=""([^""]+)""\s+value=""([^""]+)""\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, format, value
        For Each match In matches
            format = match.SubMatches(0)
            value = GetVarValue(match.SubMatches(1))
            
            Select Case LCase(format)
                Case "int"    value = Int(value)
                Case "fixed2" value = FormatNumber(value, 2)
                Case "money"  value = FormatCurrency(value)
                Case "percent" value = FormatPercent(value)
            End Select
            
            m_Content = Replace(m_Content, match.Value, value)
        Next
    End Sub
    
    '获取变量值
    Private Function GetVarValue(byval name)
        If Left(name, 1) = "$" Then
            name = Mid(name, 2)
            If m_ParseVars.Exists(name) Then
                GetVarValue = m_ParseVars(name)
            Else
                GetVarValue = ""
            End If
        Else
            GetVarValue = name
        End If
    End Function
    
    '获取对象属性值
    Private Function GetObjectValue(byval name)
        Dim parts : parts = Split(name, ".")
        Dim value
        
        If m_ParseVars.Exists(parts(0)) Then
            value = m_ParseVars(parts(0))
            If TypeName(value) = "Dictionary" Then
                GetObjectValue = value(parts(1))
            Else
                GetObjectValue = Eval("value." & parts(1))
            End If
        Else
            GetObjectValue = ""
        End If
    End Function
    
    '加载模板文件
    Private Function LoadTemplate(byval file)
        Dim cacheKey : cacheKey = "template_" & file
        
        '如果开启缓存，尝试从缓存获取
        If m_Cache Then
            LoadTemplate = Fast.Cache.Get(cacheKey)
            If LoadTemplate <> "" Then Exit Function
        End If
        
        '读取模板文件
        Dim path : path = Server.MapPath(m_TemplateDir & "/" & file & m_TemplateExt)
        LoadTemplate = FSO.ReadFile(path)
        
        '保存到缓存
        If m_Cache Then
            Fast.Cache.Set cacheKey, LoadTemplate, m_CacheTime
        End If
    End Function
    
    '解析If标签
    Private Sub ParseIfTag()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{if\s+condition=""([^""]+)""\}([\s\S]*?)(?:\{elseif\s+condition=""([^""]+)""\}([\s\S]*?))*(?:\{else\}([\s\S]*?))?\{/if\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, content, parts, i, condition
        For Each match In matches
            content = ""
            parts = Split(match.Value, "{elseif")
            
            '处理if部分
            condition = ParseOperator(GetCondition(parts(0)))
            On Error Resume Next
                If Eval(condition) Then
                    content = GetContent(parts(0))
                Else
                    '处理elseif部分
                    For i = 1 To UBound(parts)
                        condition = ParseOperator(GetCondition(parts(i)))
                        If Eval(condition) Then
                            content = GetContent(parts(i))
                            Exit For
                        End If
                    Next
                    
                    '如果所有条件都不满足，使用else部分
                    If content = "" Then
                        content = GetElseContent(match.Value)
                    End If
                End If
            On Error Goto 0
            
            m_Content = Replace(m_Content, match.Value, content)
        Next
    End Sub
    
    '获取条件表达式
    Private Function GetCondition(byval str)
        Dim reg : Set reg = New RegExp
        reg.Pattern = "condition=""([^""]+)"""
        Dim matches : Set matches = reg.Execute(str)
        If matches.Count > 0 Then
            GetCondition = matches(0).SubMatches(0)
        Else
            GetCondition = ""
        End If
    End Function
    
    '获取内容部分
    Private Function GetContent(byval str)
        Dim reg : Set reg = New RegExp
        reg.Pattern = "\}([\s\S]*?)(?:\{|$)"
        Dim matches : Set matches = reg.Execute(str)
        If matches.Count > 0 Then
            GetContent = matches(0).SubMatches(0)
        Else
            GetContent = ""
        End If
    End Function
    
    '获取else部分内容
    Private Function GetElseContent(byval str)
        Dim reg : Set reg = New RegExp
        reg.Pattern = "\{else\}([\s\S]*?)\{/if\}"
        Dim matches : Set matches = reg.Execute(str)
        If matches.Count > 0 Then
            GetElseContent = matches(0).SubMatches(0)
        Else
            GetElseContent = ""
        End If
    End Function
    
    '解析Include标签
    Private Sub ParseIncludeTag()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{include\s+file=""([^""]+)""\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, file, content
        For Each match In matches
            file = match.SubMatches(0)
            content = LoadTemplate(file)
            m_Content = Replace(m_Content, match.Value, content)
        Next
    End Sub
    
    '解析运算符
    Private Function ParseOperator(byval expr)
        '替换比较运算符
        expr = Replace(expr, " eq ", " = ")
        expr = Replace(expr, " neq ", " <> ")
        expr = Replace(expr, " gt ", " > ")
        expr = Replace(expr, " lt ", " < ")
        expr = Replace(expr, " gte ", " >= ")
        expr = Replace(expr, " lte ", " <= ")
        
        '替换逻辑运算符
        expr = Replace(expr, " and ", " AND ")
        expr = Replace(expr, " or ", " OR ")
        expr = Replace(expr, " not ", " NOT ")
        
        '替换变量
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\$([a-zA-Z0-9_\.]+)"
        
        Dim matches : Set matches = reg.Execute(expr)
        Dim match, value
        For Each match In matches
            value = GetVarValue(match.SubMatches(0))
            If IsNumeric(value) Then
                expr = Replace(expr, match.Value, value)
            Else
                expr = Replace(expr, match.Value, """" & value & """")
            End If
        Next
        
        ParseOperator = expr
    End Function
    
    '解析Switch标签
    Private Sub ParseSwitchTag()
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{switch\s+name=""([^""]+)""\}([\s\S]*?)\{/switch\}"
        
        Dim matches : Set matches = reg.Execute(m_Content)
        Dim match, name, cases, value, content
        For Each match In matches
            name = match.SubMatches(0)
            value = GetVarValue(name)
            cases = ParseCases(match.SubMatches(1))
            
            If cases.Exists(value) Then
                content = cases(value)
            ElseIf cases.Exists("default") Then
                content = cases("default")
            Else
                content = ""
            End If
            
            m_Content = Replace(m_Content, match.Value, content)
        Next
    End Sub
    
    '解析Case标签
    Private Function ParseCases(byval str)
        Dim reg : Set reg = New RegExp
        reg.Global = True
        reg.Pattern = "\{case\s+value=""([^""]+)""\}([\s\S]*?)(?:\{case|$)"
        
        Dim matches : Set matches = reg.Execute(str)
        Dim cases : Set cases = Server.CreateObject("Scripting.Dictionary")
        Dim match
        For Each match In matches
            cases.Add match.SubMatches(0), match.SubMatches(1)
        Next
        
        '解析default
        reg.Pattern = "\{default\}([\s\S]*?)(?:\{case|$)"
        Set matches = reg.Execute(str)
        If matches.Count > 0 Then
            cases.Add "default", matches(0).SubMatches(0)
        End If
        
        Set ParseCases = cases
    End Function
    
    Private Sub Class_Terminate()
        Set m_ParseVars = Nothing
    End Sub
End Class
%> 